import {computed, reactive, Ref, ref} from 'vue'
import {MsgUtil, TplUtil, EmptyUtil, AuthUtil} from '@/utils'
import {CloseModelEvent} from '@/types'

import {SysConfig} from '@/libs/config'

export class TablePage {
    public title: string

    public rowKey = 'id'

    public nameKey: string

    public dataSource = ref([])

    protected enablePagination = true

    protected permission = ''


    public searchData:Ref<Record<string, any>> = ref({})


    public theme = reactive({
        bordered: {wrapper: true, cell: true, headerCell: true},
        size: "small",
        stripe: true,
        sticky: false,
        loading: true,
        hoverAble: true,
        layoutFixed: true,
        resizable: true

    })


    public rowSelection = reactive(
        {
            type: 'checkbox',
            showCheckedAll: true,

        }
    )


    public selectedKeys = ref([])

    public pagination: boolean | any = reactive({
        current: 1,
        pageSize: 20,
        total: 0,
        hideOnSinglePage: false,
        showPageSize: true,
        showTotal: true,
    })

    /**
     * @desc 加载数据的执行方法
     * */
    private fetchXhr: any

    /**
     * @desc 删除数据的执行方法
     * */
    private deleteXhr?: any

    /**
     * @desc 导出Excle数据的请求方法
     * */
    private exportXhr?: any

    /**
     * 服务初始化
     * @param title  实例标题
     * @param rowKey   数据的主键字段名称
     * @param nameKey 数据对应的标题字段名称
     * */

    constructor({title, rowKey, nameKey = null}) {
        this.title = title
        this.rowKey = rowKey
        this.nameKey = nameKey
    }

    /**
     * @desc 初始化列表查询执行方法
     * @param xhr 列表请求方法
     * @param enablePagination 是否开启分页查询 默认开启
     * */
    setFetchXhr(xhr, enablePagination = true) {
        this.fetchXhr = xhr
        if (enablePagination === false) {
            this.pagination = false
            this.enablePagination = false
        }
        return this
    }

    /**
     * @desc 初始化数据删除执行方法
     * @param xhr 执行数据删除的执行方法
     * */
    setDeleteXhr(xhr) {
        this.deleteXhr = xhr
        return this
    }

    /*
     * 设置权限表达式
     * */
    setPermission(permissionExpr) {
        if (SysConfig.routerSource === 'SERVER') this.permission = permissionExpr
        return this
    }

    /**
     * @desc 初始化数据导出方法
     * @param xhr 执行数据导出的执行方法
     * */
    setExportXhr(xhr) {
        this.exportXhr = xhr
        return this
    }

    /**
     * @desc 添加额外的搜索条件
     * @param data 注入额外的搜索条件对象
     * */
    addSearchParams = (data: Record<string, any>) => {
        this.searchData.value = {...this.searchData.value, ...data}
    }

    /**
     * @desc  调用数据请求方法
     * */
    onFetch = async () => {
        if (typeof this.fetchXhr !== 'function') {
            MsgUtil.message('数据对象操作异常:当前实例尚未配置或初始化 【setFetchXhr】方法')
            return
        }

        if (EmptyUtil.isNotEmptyString(this.permission) && !AuthUtil.hasPermission(this.permission)) {
            MsgUtil.message(`访问当前数据查询接口需要：${this.permission}权限`)
            this.theme.loading = false
            return
        }

        this.theme.loading = true
        try {
            // 处理查询参数 如果有开启了分页功能  那么查询参数需要合并额外的分页参数
            const searchParams = this.enablePagination
                ? {...this.searchData.value, ...TplUtil.paginationCover(this.pagination.pageSize, this.pagination.current)}
                : {...this.searchData.value}

            const {data} = await this.fetchXhr(searchParams)
            if (this.enablePagination) {
                this.dataSource.value = data.records
                TplUtil.totalCover(this.pagination, data)
            } else {
                this.dataSource.value = data
            }
        } catch (e) {
            console.error(e)
        } finally {
            this.theme.loading = false
        }
    }

    /**
     * @desc  翻页方法
     * */
    onPageChange = async e => {
        if (!this.enablePagination) {
            MsgUtil.message('当前实例没有开启分页功能', 'error')
            return
        }
        this.pagination.current = e
        await this.onFetch()
    }


    onPageSizeChange = async e => {
        if (!this.enablePagination) {
            MsgUtil.message('当前实例没有开启分页功能', 'error')
            return
        }
        this.pagination.pageSize = e
        this.pagination.current = 1
        await this.onFetch()
    }


    /**
     * @desc  禁用表格批量选择
     * */
    public disableRowSelection() {
        this.selectedKeys.value = []
        return this
    }

    /**
     * @desc  删除对象
     * @param row 可选值：要删除的数据， 如果为空则删除选中的数据
     * @param callback  删除成功后执行的回调参数 不配置则重新加载数据
     *  */
    onDelete = (row: Record<string, any> = {}, callback: any = null) => {

        if (typeof this.deleteXhr !== 'function') {
            MsgUtil.message('数据对象操作异常:当前实例尚未配置或初始化 【deleteXhr】方法')
            return
        }
        let msg: string
        const data = [...this.selectedKeys.value]
        if (EmptyUtil.isNotEmptyObject(row)) {
            const tip = this.nameKey ? `【${row[this.nameKey]}】` : ''
            msg = `确定要删除${tip}这条 ${this.title} 数据吗?`
            data.push(row[this.rowKey])
        } else {

            msg = `确定要批量删除选中的 ${data.length} 条 ${this.title} 数据吗?`
        }

        const sendAjax = async () => {

            const {message} = await this.deleteXhr(data)
            MsgUtil.notify('操作成功', message)
            if (callback != null) {
                callback()
            } else {
                this.selectedKeys.value = []
                await this.onFetch()
            }
        }
        MsgUtil.confirm(msg, sendAjax, '删除确认', "确定删除")
    }


    /**
     * @desc  搜索回调
     * */
    onSearch = async (e: Record<string, any>) => {

        this.searchData.value = e
        if (this.enablePagination) this.pagination.current = 1
        await this.onFetch()
    }

    onExport = () => {
        if (typeof this.exportXhr !== 'function') {
            MsgUtil.message('尚未初始化数据导出的执行方法,请使用 【setExportXhr】方法进行初始化')
            return
        }
        const sendAjax = async () => {
            const {data} = await this.exportXhr(this.searchData.value)


            MsgUtil.downLoad(data)
        }
        const msg = `确定要根据当前查询条件导出${this.title}查询结果吗?`
        MsgUtil.confirm(msg, sendAjax, '确定导出')
    }

    /**
     * @desc  计算监听当前表格批量操作可用对象
     *  */
    public disabledBatch = computed(() => this.selectedKeys.value.length === 0)

    /**
     * 编辑弹窗控制层
     * */
    public editCtr = reactive({
        show: false,
        record: {},
        open: (e: Record<string, any> = {}) => {
            this.editCtr.show = true
            this.editCtr.record = e
        },
        close: async (e: CloseModelEvent) => {
            this.editCtr.show = false
            this.editCtr.record = {}
            if (e === 'NONE') return
            if (e === 'RELOAD' && this.enablePagination) this.pagination.current = 1
            await this.onFetch()
        },
    })

    /**
     * 只读弹窗
     * */
    public readCtr = reactive({
        show: false,
        record: {},
        open: (e: Record<string, any> = {}) => {
            this.readCtr.show = true
            this.readCtr.record = e
        },
        close: async (e: CloseModelEvent) => {

            this.readCtr.show = false
            this.readCtr.record = {}
            if (e === 'NONE') return
            if (e === 'RELOAD' && this.enablePagination) this.pagination.current = 1
            await this.onFetch()
        },
    })

    /**
     * 上传弹窗
     * */
    public uploadCtr = reactive({
        show: false,
        record: {},
        open: (e: Record<string, any> = {}) => {
            this.uploadCtr.show = true
            this.uploadCtr.record = e
        },
        close: async (e: CloseModelEvent) => {
            this.uploadCtr.show = false
            this.uploadCtr.record = {}
            if (e === 'NONE') return
            if (e === 'RELOAD' && this.enablePagination) this.pagination.current = 1
            await this.onFetch()
        },
    })
}
